/*
    Copyright 2006 Andrew Wilkinson <andrew@indiegigs.co.uk>

    This file is part of GL2x.

    GL2x is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    GL2x is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with GL2x; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#ifndef __GL2X_MATHS_H__
#define __GL2X_MATHS_H__

#define FIXED 32
#include "fixed.h"

union Vector_t {
    Fixed e[4];
    struct {
        Fixed x;
        Fixed y;
        Fixed z;
        Fixed w;
    };
    struct {
        Fixed r;
        Fixed g;
        Fixed b;
        Fixed a;
    };
};

union Matrix_t {
    Fixed col[4][4];
    Fixed e[16];
};

typedef union Vector_t Vector;
typedef union Matrix_t Matrix;

#define element(m, x, y) m.col[x][y]

#define makevector(v, a, b, c, d) v.e[0] = a; v.e[1] = b; v.e[2] = c; v.e[3] = d

unsigned char Vector_eq(const Vector this, const Vector other);
static inline Vector Vector_add(const Vector this, const Vector other) {
    Vector r;

    r.e[0] = Fixed_add(this.e[0], other.e[0]);
    r.e[1] = Fixed_add(this.e[1], other.e[1]);
    r.e[2] = Fixed_add(this.e[2], other.e[2]);
    r.e[3] = Fixed_add(this.e[3], other.e[3]);

    return r;
}

Vector Vector_sub(const Vector this, const Vector other);
Vector Vector_cross(const Vector this, const Vector other);
Vector Vector_mul(const Vector this, const Fixed other);
Vector Vector_div(const Vector this, const Fixed other);
Vector Vector_divi(const Vector this, const int other);

Vector Vector_normalize(const Vector this);
Fixed Vector_length(const Vector this);

unsigned char Matrix_eq(const Matrix this, const Matrix other);
Matrix Matrix_add(const Matrix this, const Matrix other);
Matrix Matrix_sub(const Matrix this, const Matrix other);
Matrix Matrix_mul(const Matrix this, const Matrix other);
Vector Matrix_mulv(const Matrix this, const Vector other);

Matrix Matrix_identity();
Matrix Matrix_rotate(const Fixed r, const Fixed x, const Fixed y, const Fixed z);
Matrix Matrix_scale(const Fixed x, const Fixed y, const Fixed z);
Matrix Matrix_translate(const Fixed x, const Fixed y, const Fixed z);

struct matrixstack {
    Matrix m;
    struct matrixstack* next;
};

typedef struct matrixstack matrixstack;

#endif
